#include "GRawInputDeviceKeyboard.h"
#include "GInput/GInputDefinitions.h"
#include "GInput/GInput.h"
#include "GUtilities/GTypes.h"
#include "GUtilities/GError.h"
#include "GUtilities/GBitContainer.h"

namespace GRawInput
{
	GRawInputDeviceKeyboard::GRawInputDeviceKeyboard(GEngine::GModule* Owner, void* Handle)
		: GInputDeviceKeyboard(Owner, Handle)
	{
		Reset();

		// Always keep connected
		SetConnected(true);
	}

	GRawInputDeviceKeyboard::~GRawInputDeviceKeyboard()
	{
	}

	bool GRawInputDeviceKeyboard::HandleInput(const RAWINPUT& KeyboardInput) OVERRIDE
	{
		// WM_KEYDOWN, WM_SYSKEYDOWN. Any use ?
		KeyboardInput.data.keyboard.Message;

		// Fields that are not useful
		KeyboardInput.data.keyboard.Reserved;
		KeyboardInput.data.keyboard.ExtraInformation;

		USHORT ScanCode = KeyboardInput.data.keyboard.MakeCode;
		USHORT VirtualKey = KeyboardInput.data.keyboard.VKey;

		GUtil::GFlag Flags(KeyboardInput.data.keyboard.Flags);

		// Decide left or right
		bool Left = Flags.Contains(RI_KEY_E1);
		bool Right = Flags.Contains(RI_KEY_E0);

		// If it is not break then it must be make
		bool State = !Flags.Contains(RI_KEY_BREAK);

		GSize Offset = 0;		
		switch (VirtualKey)
		{
		// Backspace
		case VK_BACK:
			Offset = GEngine::G_KS_BackSpace;
			break;
		case VK_TAB:
			Offset = GEngine::G_KS_Tab;
			break;
		case VK_RETURN:
			Offset = GEngine::G_KS_Enter;
			break;
		case VK_MENU:
			if (Left)
			{
				Offset = GEngine::G_KS_LeftAlt;
			}
			else
			{
				Offset = GEngine::G_KS_RightAlt;
			}
			break;
		case VK_CONTROL:
			if (Left)
			{
				Offset = GEngine::G_KS_LeftCtrl;
			}
			else
			{
				Offset = GEngine::G_KS_RightCtrl;
			}
			break;
		case VK_SHIFT:
			// Shift key requires scancode mapping
			switch(MapVirtualKey(ScanCode, MAPVK_VSC_TO_VK_EX))
			{
			case VK_LSHIFT:
				Offset = GEngine::G_KS_LeftShift;
				break;
			case VK_RSHIFT:
				Offset = GEngine::G_KS_RightShift;
				break;
			}
			break;
		case VK_PAUSE:
			Offset = GEngine::G_KS_Pause;
			break;
		case VK_ESCAPE:
			Offset = GEngine::G_KS_Escape;
			break;
		case VK_SPACE:
			Offset = GEngine::G_KS_Space;
			break;
		// Page up
		case VK_PRIOR:
			Offset = GEngine::G_KS_PageUp;
			break;
		// Page down
		case VK_NEXT:
			Offset = GEngine::G_KS_PageDown;
			break;
		case VK_END:
			Offset = GEngine::G_KS_End;
			break;
		case VK_HOME:
			Offset = GEngine::G_KS_Home;
			break;
		case VK_LEFT:
			Offset = GEngine::G_KS_LeftArrow;
			break;
		case VK_UP:
			Offset = GEngine::G_KS_UpArrow;
			break;
		case VK_RIGHT:
			Offset = GEngine::G_KS_RightArrow;
			break;
		case VK_DOWN:
			Offset = GEngine::G_KS_DownArrow;
			break;
		// Print screen
		case VK_SNAPSHOT:
			Offset = GEngine::G_KS_PrintScreen;
			break;
		case VK_INSERT:
			Offset = GEngine::G_KS_Insert;
			break;
		// Del key
		case VK_DELETE:
			Offset = GEngine::G_KS_Delete;
			break;
		// 0 to 9
		// Not numpad
		case 0x30:
			Offset = GEngine::G_KS_0;
			break;
		case 0x31:
			Offset = GEngine::G_KS_1;
			break;
		case 0x32:
			Offset = GEngine::G_KS_2;
			break;
		case 0x33:
			Offset = GEngine::G_KS_3;
			break;
		case 0x34:
			Offset = GEngine::G_KS_4;
			break;
		case 0x35:
			Offset = GEngine::G_KS_5;
			break;
		case 0x36:
			Offset = GEngine::G_KS_6;
			break;
		case 0x37:
			Offset = GEngine::G_KS_7;
			break;
		case 0x38:
			Offset = GEngine::G_KS_8;
			break;
		case 0x39:
			Offset = GEngine::G_KS_9;
			break;
		// A to Z
		case 0x41:
			Offset = GEngine::G_KS_A;
			break;
		case 0x42:
			Offset = GEngine::G_KS_B;
			break;
		case 0x43:
			Offset = GEngine::G_KS_C;
			break;
		case 0x44:
			Offset = GEngine::G_KS_D;
			break;
		case 0x45:
			Offset = GEngine::G_KS_E;
			break;
		case 0x46:
			Offset = GEngine::G_KS_F;
			break;
		case 0x47:
			Offset = GEngine::G_KS_G;
			break;
		case 0x48:
			Offset = GEngine::G_KS_H;
			break;
		case 0x49:
			Offset = GEngine::G_KS_I;
			break;
		case 0x4A:
			Offset = GEngine::G_KS_J;
			break;
		case 0x4B:
			Offset = GEngine::G_KS_K;
			break;
		case 0x4C:
			Offset = GEngine::G_KS_L;
			break;
		case 0x4D:
			Offset = GEngine::G_KS_M;
			break;
		case 0x4E:
			Offset = GEngine::G_KS_N;
			break;
		case 0x4F:
			Offset = GEngine::G_KS_O;
			break;
		case 0x50:
			Offset = GEngine::G_KS_P;
			break;
		case 0x51:
			Offset = GEngine::G_KS_Q;
			break;
		case 0x52:
			Offset = GEngine::G_KS_R;
			break;
		case 0x53:
			Offset = GEngine::G_KS_S;
			break;
		case 0x54:
			Offset = GEngine::G_KS_T;
			break;
		case 0x55:
			Offset = GEngine::G_KS_U;
			break;
		case 0x56:
			Offset = GEngine::G_KS_V;
			break;
		case 0x57:
			Offset = GEngine::G_KS_W;
			break;
		case 0x58:
			Offset = GEngine::G_KS_X;
			break;
		case 0x59:
			Offset = GEngine::G_KS_Y;
			break;
		case 0x5A:
			Offset = GEngine::G_KS_Z;
			break;
		case VK_SLEEP:
			Offset = GEngine::G_KS_Sleep;
			break;
		case VK_NUMPAD0:
			Offset = GEngine::G_KS_NumPad0;
			break;
		case VK_NUMPAD1:
			Offset = GEngine::G_KS_NumPad1;
			break;
		case VK_NUMPAD2:
			Offset = GEngine::G_KS_NumPad2;
			break;
		case VK_NUMPAD3:
			Offset = GEngine::G_KS_NumPad3;
			break;
		case VK_NUMPAD4:
			Offset = GEngine::G_KS_NumPad4;
			break;
		case VK_NUMPAD5:
			Offset = GEngine::G_KS_NumPad5;
			break;
		case VK_NUMPAD6:
			Offset = GEngine::G_KS_NumPad6;
			break;
		case VK_NUMPAD7:
			Offset = GEngine::G_KS_NumPad7;
			break;
		case VK_NUMPAD8:
			Offset = GEngine::G_KS_NumPad8;
			break;
		case VK_NUMPAD9:
			Offset = GEngine::G_KS_NumPad9;
			break;
		case VK_MULTIPLY:
			Offset = GEngine::G_KS_NumPadStar;
			break;
		case VK_ADD:
			Offset = GEngine::G_KS_NumPadPlus;
			break;
		case VK_SUBTRACT:
			Offset = GEngine::G_KS_NumPadMinus;
			break;
		case VK_DECIMAL:
			Offset = GEngine::G_KS_NumPadComma;
			break;
		case VK_DIVIDE:
			Offset = GEngine::G_KS_NumPadSlash;
			break;
		case VK_F1:
			Offset = GEngine::G_KS_F1;
			break;
		case VK_F2:
			Offset = GEngine::G_KS_F2;
			break;
		case VK_F3:
			Offset = GEngine::G_KS_F3;
			break;
		case VK_F4:
			Offset = GEngine::G_KS_F4;
			break;
		case VK_F5:
			Offset = GEngine::G_KS_F5;
			break;
		case VK_F6:
			Offset = GEngine::G_KS_F6;
			break;
		case VK_F7:
			Offset = GEngine::G_KS_F7;
			break;
		case VK_F8:
			Offset = GEngine::G_KS_F8;
			break;
		case VK_F9:
			Offset = GEngine::G_KS_F9;
			break;
		case VK_F10:
			Offset = GEngine::G_KS_F10;
			break;
		case VK_F11:
			Offset = GEngine::G_KS_F11;
			break;
		case VK_F12:
			Offset = GEngine::G_KS_F12;
			break;
		case VK_NUMLOCK:
			Offset = GEngine::G_KS_NumLock;
			break;
		// Scroll lock
		case VK_SCROLL:
			Offset = GEngine::G_KS_ScrollLock;
			break;
		case VK_VOLUME_MUTE:
			Offset = GEngine::G_KS_Mute;
			break;
		case VK_VOLUME_DOWN:
			Offset = GEngine::G_KS_VolumeDown;
			break;
		case VK_VOLUME_UP:
			Offset = GEngine::G_KS_VolumeUp;
			break;
		}

		CurrentState.SemanticStates[Offset] = State;

		// DEBUGGING
		//const char* StateStr = State ? "Down" : "Up";
		//const char* PositionStr = Left ? "Left" : "Right";

		//mGFileLogger->Log(G_LOG_TYPE_INFO, "Key: %s, State: %s, Position: %s", 
		//	GEngine::GKeyboardSemanticNames[Offset], StateStr, PositionStr);

		return true;
	}

}